package com.gzxx.util;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 订单号生成规则
 *
 * @author MAX
 * @date 2020/8/19 5:00 下午
 */
public class OrderGenerateRule {

    //正常下单
    private static final int PLACE_ORDER = 0;

    //异常申请
    private static final int ABNORMAL_APPLY = 1;

    //回款
    private static final int PAYMENT_COLLECTION = 2;

    //退款
    private static final int REFUND = 3;

    //积分
    private static final int INTEGRAL = 4;

    // 支付
    private static final int PAYMENT = 5;

    private static final DateTimeFormatter dateFormat
            = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

    //5位自增
    private static final AtomicLong incrOrderNum = new AtomicLong(10000);

    private static final Lock lock = new ReentrantLock();

    /**
     * 生成正常下单编号
     *
     * @return 订单号
     */
    public static String generatePlaceOrder() {
        return generateOrderNum(PLACE_ORDER);
    }

    /**
     * 生成异常申请订单编号
     *
     * @return 订单号
     */
    public static String generateABNORMALOrder() {
        return generateOrderNum(ABNORMAL_APPLY);
    }

    /**
     * 生成回款订单编号
     *
     * @return 订单号
     */
    public static String generatePaymentOrder() {
        return generateOrderNum(PAYMENT_COLLECTION);
    }

    /**
     * 生成退款订单编号
     *
     * @return 订单号
     */
    public static String generateREFUNDOrder() {
        return generateOrderNum(REFUND);
    }

    /**
     * 生成积分订单编号
     *
     * @return 订单号
     */
    public static String generateINTEGRALOrder() {
        return generateOrderNum(INTEGRAL);
    }

    /**
     * 生成支付订单编号
     *
     * @return
     */
    public static String generatePAYMENTOrder() {
        return generateOrderNum(PAYMENT);
    }

    /**
     * 可以应对每秒8-9w并发
     * 订单编号生成
     *
     * @param orderType 订单类型
     * @return 订单号
     */
    private static String generateOrderNum(int orderType) {
        if (incrOrderNum.get() > 99999L) {
            try {
                lock.lock();
                //双重检测
                if (incrOrderNum.get() > 99999L) {
                    incrOrderNum.set(10000);
                }
            } finally {
                lock.unlock();
            }
        }
        String currentDate = dateFormat.format(LocalDateTime.now());
        long incrNum = incrOrderNum.getAndIncrement();
        //订单类型+当前时间(年月日时分秒)+自增订单号
        return orderType + currentDate + incrNum;
    }
}
